﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Threading;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Tagging;
using MyExtendProject.Editors.Models;

namespace MyExtendProject.Editors.Region
{
    internal sealed class RegionTagger:ITagger<IOutliningRegionTag>
    {
        // Token: 0x04000005 RID: 5
        private string _startHide = "// #region";

        // Token: 0x04000006 RID: 6
        private string _endHide = "// #endregion";

        // Token: 0x04000007 RID: 7
        private string _hoverText = "Collapsed content";

        // Token: 0x04000008 RID: 8
        private ITextBuffer _buffer;

        // Token: 0x04000009 RID: 9
        private ITextSnapshot _snapshot;

        // Token: 0x0400000A RID: 10
        private List<PartialRegion> _regions;

        // Token: 0x0400000B RID: 11
        private static Regex _regex = new Regex("\\/\\/\\ ?\\#region(.*)?", RegexOptions.Compiled);

        public RegionTagger(ITextBuffer buffer)
        {
            this._buffer = buffer;
            this._snapshot = buffer.CurrentSnapshot;
            this._regions = new List<PartialRegion>();
            this._buffer.Changed += this.BufferChanged;

            ThreadHelper.Generic.BeginInvoke(DispatcherPriority.ApplicationIdle, delegate ()
            {
                this.ReParse();
            });
            this._buffer.Changed += this.BufferChanged;
        }

        // Token: 0x0600000F RID: 15 RVA: 0x0000222F File Offset: 0x0000042F
        public IEnumerable<ITagSpan<IOutliningRegionTag>> GetTags(NormalizedSnapshotSpanCollection spans)
        {
            if (spans.Count == 0)
            {
                yield break;
            }
            List<PartialRegion> regions = this._regions;
            ITextSnapshot currentSnapshot = this._snapshot;
            SnapshotSpan snapshotSpan = new SnapshotSpan(spans[0].Start, spans[spans.Count - 1].End).TranslateTo(currentSnapshot, 0);
            int startLineNumber = snapshotSpan.Start.GetContainingLine().LineNumber;
            int endLineNumber = snapshotSpan.End.GetContainingLine().LineNumber;
            foreach (PartialRegion region in regions)
            {
                if (region.StartLine <= endLineNumber && region.EndLine >= startLineNumber)
                {
                    ITextSnapshotLine lineFromLineNumber = currentSnapshot.GetLineFromLineNumber(region.StartLine);
                    ITextSnapshotLine lineFromLineNumber2 = currentSnapshot.GetLineFromLineNumber(region.EndLine);
                    SnapshotSpan snapshotSpan2 = new SnapshotSpan(lineFromLineNumber.Start + region.StartOffset, lineFromLineNumber2.End);
                    Match match = _regex.Match(snapshotSpan2.GetText());
                    string str = string.IsNullOrWhiteSpace(match.Groups[1].Value) ? "#region" : match.Groups[1].Value.Trim();
                    yield return new TagSpan<IOutliningRegionTag>(snapshotSpan2, new OutliningRegionTag(false, true, " " + str + " ", this._hoverText));
                }
            }
            yield break;
        }

        // Token: 0x14000002 RID: 2
        // (add) Token: 0x06000010 RID: 16 RVA: 0x00002248 File Offset: 0x00000448
        // (remove) Token: 0x06000011 RID: 17 RVA: 0x00002280 File Offset: 0x00000480
        public event EventHandler<SnapshotSpanEventArgs> TagsChanged;

        // Token: 0x06000012 RID: 18 RVA: 0x000022B5 File Offset: 0x000004B5
        private void BufferChanged(object sender, TextContentChangedEventArgs e)
        {
            if (e.After != this._buffer.CurrentSnapshot)
            {
                return;
            }
            Dispatcher.CurrentDispatcher.BeginInvoke(new Action(delegate ()
            {
                this.ReParse();
            }), DispatcherPriority.ApplicationIdle, null);
        }

        // Token: 0x06000013 RID: 19 RVA: 0x000022E4 File Offset: 0x000004E4
        private void ReParse()
        {
            ITextSnapshot newSnapshot = this._buffer.CurrentSnapshot;
            List<PartialRegion> list = new List<PartialRegion>();
            PartialRegion partialRegion = null;
            foreach (ITextSnapshotLine textSnapshotLine in newSnapshot.Lines)
            {
                string text = textSnapshotLine.GetText();
                int num;
                if ((num = text.IndexOf(this._startHide, StringComparison.Ordinal)) != -1 || (num = text.IndexOf(this._startHide.Replace(" ", string.Empty), StringComparison.Ordinal)) != -1)
                {
                    int num2 = (partialRegion != null) ? partialRegion.Level : 1;
                    int num3;
                    if (!RegionTagger.TryGetLevel(text, num, out num3))
                    {
                        num3 = num2 + 1;
                    }
                    if (num2 == num3 && partialRegion != null)
                    {
                        list.Add(new PartialRegion
                        {
                            Level = partialRegion.Level,
                            StartLine = partialRegion.StartLine,
                            StartOffset = partialRegion.StartOffset,
                            EndLine = textSnapshotLine.LineNumber
                        });
                        partialRegion = new PartialRegion
                        {
                            Level = num3,
                            StartLine = textSnapshotLine.LineNumber,
                            StartOffset = num,
                            PartialParent = partialRegion.PartialParent
                        };
                    }
                    else
                    {
                        partialRegion = new PartialRegion
                        {
                            Level = num3,
                            StartLine = textSnapshotLine.LineNumber,
                            StartOffset = num,
                            PartialParent = partialRegion
                        };
                    }
                }
                else if ((num = text.IndexOf(this._endHide, StringComparison.Ordinal)) != -1 || (num = text.IndexOf(this._endHide.Replace(" ", string.Empty), StringComparison.Ordinal)) != -1)
                {
                    int num4 = (partialRegion != null) ? partialRegion.Level : 1;
                    int num5;
                    if (!RegionTagger.TryGetLevel(text, num, out num5))
                    {
                        num5 = num4;
                    }
                    if (partialRegion != null && num4 == num5)
                    {
                        list.Add(new PartialRegion
                        {
                            Level = num4,
                            StartLine = partialRegion.StartLine,
                            StartOffset = partialRegion.StartOffset,
                            EndLine = textSnapshotLine.LineNumber
                        });
                        partialRegion = partialRegion.PartialParent;
                    }
                }
            }
            IEnumerable<Span> enumerable = new List<Span>(from r in this._regions
                                                          select RegionTagger.AsSnapshotSpan(r, this._snapshot).TranslateTo(newSnapshot, 0).Span);
            List<Span> list2 = new List<Span>(from r in list
                                              select RegionTagger.AsSnapshotSpan(r, newSnapshot).Span);
            NormalizedSpanCollection normalizedSpanCollection = new NormalizedSpanCollection(enumerable);
            NormalizedSpanCollection normalizedSpanCollection2 = new NormalizedSpanCollection(list2);
            NormalizedSpanCollection normalizedSpanCollection3 = NormalizedSpanCollection.Difference(normalizedSpanCollection, normalizedSpanCollection2);
            int num6 = int.MaxValue;
            int num7 = -1;
            if (normalizedSpanCollection3.Count > 0)
            {
                num6 = normalizedSpanCollection3[0].Start;
                num7 = normalizedSpanCollection3[normalizedSpanCollection3.Count - 1].End;
            }
            if (list2.Count > 0)
            {
                num6 = Math.Min(num6, list2[0].Start);
                num7 = Math.Max(num7, list2[list2.Count - 1].End);
            }
            this._snapshot = newSnapshot;
            this._regions = list;
            if (num6 <= num7)
            {
                EventHandler<SnapshotSpanEventArgs> tagsChanged = this.TagsChanged;
                if (tagsChanged == null)
                {
                    return;
                }
                tagsChanged(this, new SnapshotSpanEventArgs(new SnapshotSpan(this._snapshot, Span.FromBounds(num6, num7))));
            }
        }

        // Token: 0x06000014 RID: 20 RVA: 0x0000262C File Offset: 0x0000082C
        private static bool TryGetLevel(string text, int startIndex, out int level)
        {
            level = -1;
            return text.Length > startIndex + 3 && int.TryParse(text.Substring(startIndex + 1), out level);
        }

        // Token: 0x06000015 RID: 21 RVA: 0x00002650 File Offset: 0x00000850
        private static SnapshotSpan AsSnapshotSpan(PartialRegion region, ITextSnapshot snapshot)
        {
            ITextSnapshotLine lineFromLineNumber = snapshot.GetLineFromLineNumber(region.StartLine);
            ITextSnapshotLine textSnapshotLine = (region.StartLine == region.EndLine) ? lineFromLineNumber : snapshot.GetLineFromLineNumber(region.EndLine);
            return new SnapshotSpan(lineFromLineNumber.Start + region.StartOffset, textSnapshotLine.End);
        }

    }
}
